#pragma once

#include <cstddef>
#include <cstdint>

#include <memory>

#include "Error.h"
#include "TimerTask.h"

namespace frame {
namespace imp {

class ServerImp;
class ServerChannelImp;

class HandlerImp{
public:
    HandlerImp()
    :serverImp(nullptr)
    {
    }
    virtual ~HandlerImp() {
    }
    void setServerImp(ServerImp  * imp){
        this->serverImp = imp;
    }
    ServerImp *  getServerImp() const {
        return this->serverImp;
    }

    virtual void connected(ServerChannelImp* serverChannelImp) = 0;
    virtual void disconnected(ServerChannelImp* serverChannelImp, Error error) = 0;

    virtual void read(ServerChannelImp * serverChannelImp, const char * buf,  std::size_t size) = 0;
    virtual void readException(ServerChannelImp * serverChannelImp, int error) = 0 ;

    virtual void writed(ServerChannelImp * serverChannelImp, std::size_t size) = 0 ;
    virtual void writeException(ServerChannelImp * serverChannelImp, int error) = 0;

private:
    ServerImp * serverImp;     
};

class ServerChannelImp
{
public:
    ServerChannelImp(uint64_t id, ServerImp * serverImp) : id(id), serverImp(serverImp){}
    virtual ~ServerChannelImp(){}

    uint64_t getId() const { return id;}
    ServerImp *  getServerImp() const {
        return this->serverImp;
    }
    virtual std::string getRemoteIp() = 0;
    virtual const int getRemotePort() = 0;


    virtual bool open() = 0; //register timer
    virtual bool close() = 0; //cancel timer & destroy it

    virtual void write(const char * buf, int size) = 0; 
    virtual void disconnect() = 0;

private: 
    const uint64_t id;
    ServerImp * serverImp;
};


class UniqueNumber;
class DefaultHandlerImp;

class ServerImp {
public:
    ServerImp(const int port = 0);
    virtual ~ServerImp();

    int getPort() const {
        return port;
    }
    void setPort(const int port) {
        this->port =  port;
    }
    virtual void setHandler(HandlerImp * handler) {
        this->handler = handler;
        handler->setServerImp(this);
    }
    HandlerImp * getHandler() const {
        return handler;
    }

    UniqueNumber & getChannelNumber(){
        return *channelNumber;
    }

    virtual int start();
    virtual int run() = 0;
    virtual void stop() = 0;

    virtual uint64_t addTimerTask(ITimerTask * task, uint64_t timespan) = 0;
    virtual void removeTimerTask(uint64_t timerId) = 0;

private:
    int port;
    HandlerImp * handler;
    UniqueNumber *channelNumber;
};

} //end of namespace  imp
} //end of namespace  frame
